Sh.Parser.UserText = new Class({
	initialize : function (text) {
		this.text  = text;
		this.parse();
	},
	get : function () {
		return this.p;
	},
	parse : function () {
		this.p = [];

		this.newStr = true;
		this.esc = false;
		this.dqS = false;
		this.sqS = false;
		this.text
			.toArray()
			.each(function (L) {
				this.letter = L;
				this.last = this.p.getLast();
				this.parseLetter();
			}.bind(this)
		);

		if (this.dqS || this.sqS) {
			if (this.newStr) {
				this.p.push({
					type  : 'string',
					value : '',
					open  : true
				});
			} else {
				this.p.getLast().open = true;
			}
		} else if (this.esc) {
			this.p.push({
				type : 'escape'
			})
		}

		return this.p;
	},
	parseLetter : function () {
		var L = this.letter;
		var last = this.last;
		if (this.isSymbol()) {
			return
		} else {
			this.esc = false;
			if (this.checkNl()) {
				return;
			}
		}
		if (!this.newStr && last && last.type == 'string') {
			last.value += L;
		} else {
			this.newStr = false;
			this.p.push({
				type  : 'string',
				value : L
			})
		}
	},
	checkQuote : function () {
		var L      = this.letter;
		if (L == '"' && !this.sqS) {
			this.dqS = !this.dqS;
			return true;
		} else if (L == "'" && !this.dqS) {
			this.sqS = !this.sqS;
			return true;
		}
		return false;
	},
	checkEscape : function () {
		if(this.letter == '\\') {
			this.esc = true;
			return true;
		} else {
			return false;
		}
	},
	isQuotedString : function () {
		return this.dqS || this.sqS;
	},
	checkSpace : function () {
		if (this.letter == ' ') {
			if (!this.last || this.last.type != 'string' || this.last.value.length > 0) {
				this.newStr = true;
			}
			return true;
		} else {
			return false;
		}
	},
	checkOperand : function () {
		var last = this.last;
		var L     = this.letter;
		if (['&', '|', '>', '<', ';'].contains(L)) {
			// @todo ban too long operands
			if (last.type == 'operand' && last.value[0] == L) {
				last.value += L;
			} else {
				this.p.push({
					type  : 'operand',
					value : L
				})
			}
			return true;
		}
		return false;
	},
	isSymbol : function () {
		if (this.esc) {
			return false;
		}
		if (this.checkQuote() || this.checkEscape()) {
			return true;
		} else if (!this.isQuotedString()) {
			if (this.checkSpace() || this.checkOperand()) {
				return true;
			}
		}
		return false;
	},
	checkNl : function () {
		if (!this.isQuotedString() && this.letter == '\n') {
			this.p.push({
				type : 'nl'
			})
			return true;
		} else {
			return false;
		}
	}
});

